﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Algoritmia.Problems.GasStations;

namespace Demos.GasStations
{
    class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public ObservableCollection<ElementoVisual> ContenidoVisual { get; set; }

        private double _distanciaNueva;
        public double DistanciaNueva
        {
            get { return _distanciaNueva; }
            set
            {
                _distanciaNueva = value;
                NotifyPropertyChanged("DistanciaNueva");
            }
        }

        private double _duracionAnimacion;
        public double DuracionAnimacion
        {
            get { return _duracionAnimacion; }
            set
            {
                _duracionAnimacion = value;
                NotifyPropertyChanged("DuracionAnimacion");
            }
        }

        public ICommand AñadirEstacionCommand { get; private set; }
        public ICommand ComenzarCommand { get; private set; }
        public ICommand BorrarCommand { get; private set; }

        private readonly GasStationRoutePlanner _model;
        private const double DistanciaEntreEstaciones = 150;
        private const double AnchuraEstacion = 40;
        private int _numeroEstaciones;
        private const int CapacidadInicial = 150;
        private readonly Line _lineaAnimacion;
        private enum Animaciones { Viajar, Parar };
        private List<Animaciones> _acciones;


        public ViewModel(GasStationRoutePlanner model)
        {
            _model = model;
            DistanciaNueva = 100;
            DuracionAnimacion = 500;
            _lineaAnimacion = new Line();

            ContenidoVisual = new ObservableCollection<ElementoVisual> {new Coche(-10, 150, CapacidadInicial)};

            AñadirEstacionCommand = new RelayCommand(AñadirEstacion, () => DistanciaNueva > 0);
            BorrarCommand = new RelayCommand(Borrar, () => ContenidoVisual.Count > 1);
            ComenzarCommand = new RelayCommand(Comenzar, () => ContenidoVisual.Count > 1);

            //Estaciones de ejemplo
            DistanciaNueva = 65;
            AñadirEstacion();
            DistanciaNueva = 23;
            AñadirEstacion();
            DistanciaNueva = 45;
            AñadirEstacion();
            DistanciaNueva = 62;
            AñadirEstacion();
            DistanciaNueva = 12;
            AñadirEstacion();
            DistanciaNueva = 100;
        }


        private void Comenzar()
        {
            _acciones = new List<Animaciones>();
            var distancias = new Algoritmia.DataStructures.Lists.ArrayList<double>();
            foreach (var elementoVisual in ContenidoVisual)
            {
                if (elementoVisual.GetType() == typeof(Estacion))
                {
                    distancias.Add((elementoVisual as Estacion).Distancia);
                }
            }

            var solucion = _model.Plan(distancias, (ContenidoVisual.First() as Coche).Capacidad);
            AlmacenarSolucion(solucion);
        }

        private void Borrar()
        {
            ContenidoVisual.Clear();
            ContenidoVisual.Add(new Coche(-10, 150, CapacidadInicial));
            _numeroEstaciones = 0;
        }

        private void AñadirEstacion()
        {
            if (ContenidoVisual.Count <= 1)
            {
                ContenidoVisual.Add(new Estacion(10, 10, DistanciaNueva));
                _numeroEstaciones++;
            }
            else
            {
                ContenidoVisual.Add(new Carretera(0, 100,
                    DistanciaEntreEstaciones, 100, 
                    ContenidoVisual.Last().X + AnchuraEstacion, 0, (ContenidoVisual.Last() as Estacion).Distancia));
                ContenidoVisual.Add(new Estacion(ContenidoVisual.Last().X+DistanciaEntreEstaciones, 10, DistanciaNueva));
                _numeroEstaciones++;
            }
        }

        private void AlmacenarSolucion(Algoritmia.DataStructures.Lists.IList<int> solucion)
        {
            if (solucion.Count == 0)
            {
                MessageBox.Show("Sin solución", "Aviso", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }
            for (int i = 0; i < _numeroEstaciones-1; i++)
            {
                if (i == solucion.First())
                {
                    solucion.RemoveAt(0);
                    _acciones.Add(Animaciones.Viajar);
                    _acciones.Add(Animaciones.Parar);
                }
                else
                {
                    _acciones.Add(Animaciones.Viajar);
                }
            }
            AnimarSolucion(null, EventArgs.Empty);
        }

        private void AnimarSolucion(object o, EventArgs e)
        {
            if (_acciones.Count == 0)
            {
                return;
            }

            switch (_acciones.First())
            {
                case Animaciones.Viajar:
                    _acciones.RemoveAt(0);
                    AnimarViaje();
                    break;
                case Animaciones.Parar:
                    _acciones.RemoveAt(0);
                    AnimarParada();
                    break;
            }
        }

        private void AnimarViaje()
        {
            var duration1 = new Duration(TimeSpan.FromMilliseconds(DuracionAnimacion));
            var sb1 = new Storyboard();
            sb1.Completed += AnimarSolucion;
            var myDoubleAnimation1 = new DoubleAnimation {Duration = duration1};
            sb1.Duration = duration1;
            sb1.Children.Add(myDoubleAnimation1);
            Storyboard.SetTarget(myDoubleAnimation1, ContenidoVisual.First());
            Storyboard.SetTargetProperty(myDoubleAnimation1, new PropertyPath("(X)"));
            myDoubleAnimation1.From = ContenidoVisual.First().X;
            myDoubleAnimation1.To = ContenidoVisual.First().X + DistanciaEntreEstaciones + AnchuraEstacion;
            sb1.Begin();
        }

        private void AnimarParada()
        {
            var sb1 = new Storyboard();
            sb1.Completed += AnimarSolucion;
            var duration1 = new Duration(TimeSpan.FromMilliseconds(DuracionAnimacion));
            var myDoubleAnimation1 = new DoubleAnimation { Duration = duration1 };
            sb1.Duration = duration1;
            sb1.Children.Add(myDoubleAnimation1);
            Storyboard.SetTargetProperty(myDoubleAnimation1, new PropertyPath("(Canvas.Left)"));
            Storyboard.SetTarget(myDoubleAnimation1, _lineaAnimacion);
            myDoubleAnimation1.From = 0;
            myDoubleAnimation1.To = 1;
            sb1.Begin();
        }
    }
}
